package models

import (
	"fmt"
	"time"

	"github.com/beego/beego/v2/client/orm"
)

// PointsLog 会员积分变动记录模型
type PointsLog struct {
	BaseModel
	MemberId     int64  `orm:"index" json:"member_id"`          // 会员ID
	Points       int    `orm:"default(0)" json:"points"`        // 变动积分数量，正数为增加，负数为减少
	Type         int8   `orm:"default(1)" json:"type"`          // 变动类型：1:消费获得, 2:管理员调整, 3:活动奖励, 4:签到奖励, 5:积分兑换
	OrderNo      string `orm:"size(64)" json:"order_no"`        // 关联订单号
	Description  string `orm:"size(255)" json:"description"`    // 变动描述
	Operator     string `orm:"size(64)" json:"operator"`        // 操作人
	BeforePoints int    `orm:"default(0)" json:"before_points"` // 变动前积分
	AfterPoints  int    `orm:"default(0)" json:"after_points"`  // 变动后积分
}

// TableName 设置表名
func (p *PointsLog) TableName() string {
	return "ss_points_log"
}

// GetPointsLogById 根据ID获取积分变动记录
func GetPointsLogById(id int64, franchiseId int64) (*PointsLog, error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(PointsLog)).Filter("id", id).Filter("is_deleted", 0)

	// 加盟商过滤
	if franchiseId > 0 {
		// 获取该加盟商下的所有会员ID
		var memberIds orm.ParamsList
		_, err := o.QueryTable(new(Member)).
			Filter("franchise_id", franchiseId).
			Filter("is_deleted", 0).
			ValuesFlat(&memberIds, "id")
		if err != nil {
			return nil, err
		}
		if len(memberIds) > 0 {
			qs = qs.Filter("member_id__in", memberIds)
		}
	}

	pointsLog := &PointsLog{}
	err := qs.One(pointsLog)
	return pointsLog, err
}

// GetPointsLogList 获取积分变动记录列表
func GetPointsLogList(page, pageSize int, filters map[string]interface{}) ([]*PointsLog, int64, error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(PointsLog))

	// 应用过滤条件
	if memberId, ok := filters["member_id"].(int64); ok {
		qs = qs.Filter("member_id", memberId)
	}

	if logType, ok := filters["type"].(int8); ok {
		qs = qs.Filter("type", logType)
	}

	if orderNo, ok := filters["order_no"].(string); ok && orderNo != "" {
		qs = qs.Filter("order_no", orderNo)
	}

	// 积分大于某值
	if pointsGt, ok := filters["points_gt"].(int); ok {
		qs = qs.Filter("points__gt", pointsGt)
	}

	// 积分小于某值
	if pointsLt, ok := filters["points_lt"].(int); ok {
		qs = qs.Filter("points__lt", pointsLt)
	}

	// 时间范围过滤
	if startTime, ok := filters["start_time"].(int64); ok {
		qs = qs.Filter("created_at__gte", startTime)
	}

	if endTime, ok := filters["end_time"].(int64); ok {
		qs = qs.Filter("created_at__lte", endTime)
	}

	// 加盟商过滤
	if franchiseId, ok := filters["franchise_id"].(int64); ok && franchiseId > 0 {
		// 获取该加盟商下的所有会员ID
		var memberIds orm.ParamsList
		_, err := o.QueryTable(new(Member)).
			Filter("franchise_id", franchiseId).
			Filter("is_deleted", 0).
			ValuesFlat(&memberIds, "id")
		if err != nil {
			return nil, 0, err
		}
		if len(memberIds) > 0 {
			qs = qs.Filter("member_id__in", memberIds)
		}
	}

	// 排除已删除的记录
	qs = qs.Filter("is_deleted", 0)

	// 获取总数
	total, _ := qs.Count()

	// 分页查询
	var pointsLogs []*PointsLog
	_, err := qs.OrderBy("-id").Limit(pageSize, (page-1)*pageSize).All(&pointsLogs)

	return pointsLogs, total, err
}

// CreatePointsLog 创建积分变动记录
func CreatePointsLog(pointsLog *PointsLog, franchiseId int64) (int64, error) {
	o := orm.NewOrm()

	// 验证会员是否属于该加盟商
	if franchiseId > 0 {
		qs := o.QueryTable(new(Member)).
			Filter("id", pointsLog.MemberId).
			Filter("franchise_id", franchiseId).
			Filter("is_deleted", 0)

		exists := qs.Exist()
		if !exists {
			return 0, fmt.Errorf("会员不属于该加盟商")
		}
	}

	id, err := o.Insert(pointsLog)
	return id, err
}

// AddMemberPoints 增加会员积分并记录
func AddMemberPoints(memberId int64, points int, logType int8, orderNo, description, operator string, franchiseId int64) error {
	// 开启事务
	o := orm.NewOrm()
	tx, err := o.Begin()
	if err != nil {
		return err
	}

	// 获取会员信息
	qs := o.QueryTable(new(Member)).Filter("id", memberId).Filter("is_deleted", 0)

	// 加盟商过滤
	if franchiseId > 0 {
		qs = qs.Filter("franchise_id", franchiseId)
	}

	member := &Member{}
	err = qs.One(member)
	if err != nil {
		tx.Rollback()
		return err
	}

	// 记录变动前积分
	beforePoints := member.Points

	// 更新会员积分
	member.Points += points
	member.UpdatedAt = time.Now().Unix()
	_, err = o.Update(member, "Points", "UpdatedAt")
	if err != nil {
		tx.Rollback()
		return err
	}

	// 创建积分变动记录
	pointsLog := &PointsLog{
		MemberId:     memberId,
		Points:       points,
		Type:         logType,
		OrderNo:      orderNo,
		Description:  description,
		Operator:     operator,
		BeforePoints: beforePoints,
		AfterPoints:  member.Points,
	}
	pointsLog.BeforeInsert()
	_, err = o.Insert(pointsLog)
	if err != nil {
		tx.Rollback()
		return err
	}

	// 提交事务
	return tx.Commit()
}
